<template>
  <div>
    <div style="padding: 0 10px 10px">
      背景色：
      <el-color-picker v-model="style.background" size="small"></el-color-picker>&nbsp;
      文字颜色：
      <el-color-picker v-model="style.color" size="small"></el-color-picker>&nbsp;
    </div>
    <div style="height: 80vh;">
      <vue3-tree-org
          :data="data"
          center
          :horizontal="horizontal"
          :label-style="style"
          :only-one-node="onlyOneNode"
          :clone-node-drag="cloneNodeDrag"
          :node-draggable="nodeDraggable"
          :before-drag-end="beforeDragEnd"
          :define-menus="defineMenus"
          @on-node-drag="nodeDragMove"
          @on-node-drag-end="nodeDragEnd"
          @on-contextmenu="onMenus"
          @on-expand="onExpand"
          @on-node-dblclick="onNodeDblclick"
          @on-node-click="onNodeClick"
          @on-node-blur="onNodeBlur"
      >
        <!-- 自定义节点内容 -->
        <template v-slot="{node}">
          <div class="tree-org-node__text node-label">
            <div><b>{{ node.label }}</b></div>
            <div class="custom-content" v-if="node.pid != null">状态：
              <span v-if="node.$$data.status == 1" style="color:#42b983">{{ node.$$data.statusText }}</span>
              <span v-else style="color:coral">{{ node.$$data.statusText }}</span>
            </div>
          </div>
        </template>
      </vue3-tree-org>
    </div>

    <el-dialog
        :title="dialogDepTitle"
        style="width: 35vh;padding:20px;"
        v-model="dialogDepVisible"
        :before-close="handleDepClose"
        align-center
    >
      <el-form label-width="80px" label-position="left">
        <el-form-item label="部门名称">
          <el-input placeholder="请输入部门名称" v-model="saveDepData.name"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="handleDepClose">取消</el-button>
        <el-button type="primary" @click="savaDep">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import {ElMessage} from 'element-plus'
import {onMounted, ref} from 'vue'
import {Vue3TreeOrg} from "vue3-tree-org";
import axios from "/src/api/axios";

const dialogDepTitle = ref("新增部门");
const dialogDepVisible = ref(false);
const saveDepData = ref({});
const data = ref({});
const horizontal = ref(false);
const onlyOneNode = ref(false);
const expandAll = ref(true);
const nodeDraggable = ref(true);
const cloneNodeDrag = ref(false);

const style = ref({
  background: "#fff",
  color: "#5e6d82",
});

onMounted(() => {
  loadDep();
});

// 删除部门
const del = (node) => {
  if (confirm("是否删除【" + node.label + "】")) {
    axios.delete("/v1/department/delete", {
      serviceName: 'departmentService', params: {
        id: node.id,
        pid: node.pid
      }
    }).then((response) => {
      if (response.data.code === 200) {
        ElMessage.success(response.data.msg || '删除成功');
        loadDep();
      } else {
        ElMessage.error(response.data.msg || "删除失败")
      }
    })
    // 实现删除逻辑
  } else {
    // 取消删除
  }
}

// 加载部门
const loadDep = () => {
  axios.get('/v1/department/getTree', {
    serviceName: 'departmentService'
  }).then(response => {
    data.value = response.data.data;
  })
}

// 新增部门
const addDep = (node) => {
  dialogDepTitle.value = "新增部门";
  dialogDepVisible.value = true;
  saveDepData.value = {
    pid: node.id,
  };
}

//关闭新增/编辑部门弹窗
const handleDepClose = () => {
  dialogDepVisible.value = false;
  saveDepData.value = {};
}

// 编辑部门
const editDep = (node) => {
  dialogDepTitle.value = "编辑部门";
  dialogDepVisible.value = true;
  saveDepData.value = {id: node.id, name: node.label, pid: node.pid}
}

// 修改状态
const changeStatus = (node) => {
  axios.get('/v1/department/changeStatus', {
    serviceName: 'departmentService',
    params: {id: node.id, pid: node.pid}
  }).then((response) => {
    if (response.data.code === 200) {
      ElMessage.success(response.data.msg || '操作成功');
      loadDep();
    } else {
      ElMessage.error(response.data.msg || "系统错误");
    }
  })
}

/**
 * 保存修改/新增后的数据
 */
const savaDep = () => {
  axios.post("/v1/department/update", saveDepData.value, {serviceName: 'departmentService'}).then((response) => {
    if (response.data.code === 200) {
      ElMessage.success(response.data.msg || '保存成功');
      handleDepClose();
      loadDep();
    } else {
      ElMessage.error(response.data.msg || "保存失败")
    }
  })
}

// 右键菜单点击选中某个选项后的事件
const onMenus = ({node, command}) => {
  switch (command) {
    case 'del':
      del(node);
      break;
    case 'addDep':
      addDep(node);
      break;
    case 'editDep':
      editDep(node);
      break;
    case 'changeStatus':
      changeStatus(node);
      break;
  }
}

// 节点展开事件
const onExpand = (e, data) => {
  // console.log(e, data);
}

// 节点拖拽事件
const nodeDragMove = (data) => {
  // console.log(data);
}

// 节点拖拽结束前钩子（参数当前节点node, 目标节点targetNode），若返回 false 或者返回 Promise 且被 reject，则阻止节点拖拽
const beforeDragEnd = (node, targetNode) => {
  return new Promise((resolve, reject) => {
    if (!targetNode) reject();
    if (node.id === targetNode.id) {
      reject();
    } else {
      resolve();
    }
    console.log(node.id, targetNode.id);
  });
}

// 自定义右键菜单
const defineMenus = (e, node) => {
  let statusHandleString = '启用';

  console.log(node);
  if (node.$$data.status == "1") {
    statusHandleString = '禁用';
  }

  if (node.pid == null) {
    // 顶级部门不允许删除和启用/禁用
    return [
      {name: '新建下级部门', command: 'addDep'},
      {name: '编辑', command: 'editDep'},
      // {name: statusHandleString, command: 'changeStatus'},
    ];
  } else {
    return [
      {name: '新建下级部门', command: 'addDep'},
      {name: '编辑', command: 'editDep'},
      {name: statusHandleString, command: 'changeStatus'},
      {name: '删除', command: 'del'},
    ];
  }
}

// 节点拖拽结束的事件(拖拽的节点,拖拽到的目标节点)
const nodeDragEnd = (data, parent) => {
  if (data.pid === parent.id) {
    return;
  } else {
    axios.post('/v1/department/update', {
      id: data.id,
      pid: parent.id,
    }, {serviceName: 'departmentService'}).then(response => {
      if (response.data.code !== 200) {
        return new Promise((resolve, reject) => {
          ElMessage.error(response.data.msg || '更新失败');
          resolve();
        });
      }
    })
  }
}

// 节点双击事件
const onNodeDblclick = () => {
  // console.log('onNodeDblclick');
}

// 节点单击事件
const onNodeClick = (e, data) => {
  // ElMessage.info(data.label);
}

// 节点失去焦点的事件
const onNodeBlur = (e, data) => {
}

// 展开状态改变时触发
const expandChange = () => {
  // 更新所有节点的展开状态
  toggleExpand(data.value, expandAll.value);
}

// 切换所有节点的展开状态
const toggleExpand = (data, val) => {
  if (Array.isArray(data)) {
    data.forEach((item) => {
      item.expand = val;
      if (item.children) {
        toggleExpand(item.children, val);
      }
    });
  } else {
    data.expand = val;
    if (data.children) {
      toggleExpand(data.children, val);
    }
  }
}

// 在 created 钩子中更新所有节点的展开状态
onMounted(() => {
  toggleExpand(data.value, expandAll.value);
});
</script>

<style>
.tree-org {
  margin-top: 10px;
}

.zm-tree-contextmenu {
  line-height: 20px;
}
</style>